using System;
using System.Collections.Generic;
using System.Text;
using TaugeLibrary.Classes.Attributes;
using TaugeLibrary.Classes.Abstracts;
using System.Collections;
using TaugeLibrary.Classes;
using TaugeFramework.Classes;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using System.Windows.Forms;
using TaugeLibrary.Enums;
using TaugeLibrary.Interfaces;

namespace TaugeFramework.BusinessUnit.User
{

    public enum eUserType
    {
        USER = 0,
        GROUP = 1
    }
    
    /*
    [
    AttBu(
            TableName = "UserAccount",
            PrimaryKeys = new string[] { "UserId" },
            DataPKeys = new string[] { "UserId" },
            PropPKeys = new string[] { "UserId" },
            DBType = LibConstants.DBSYS
    )
    ]
     * */
    [AttTable("UserAccount","UA")]
    [AttPrimaryKey("UserId")]
    [AttUniqueKey("UserName")]        
    class UserAccount : ABusinessUnit
    {


        //public static readonly LookupParameter UserGroupLookupParameter = new LookupParameter("SELECT * FROM UserAccount WHERE UserType='GROUP' AND IsActive=1 ", "Username", "Username", "User Group List");


        #region memvar
        private int m_userid;
        private string m_username;
        private string m_userdesc;
        private string m_password_enc;
        private eUserType m_usertype;
        private Boolean m_isactive;
        private string m_email_address;
        private int m_ceksum = 0;

        private Hashtable m_accesses = new Hashtable();
        private Hashtable m_groups = new Hashtable();
        private Hashtable m_companies = new Hashtable();
        private Hashtable m_current_accesses = new Hashtable();
        #endregion

        #region prop

        [AttField("UserId",eDBDataType.IDENTITY,0,"Id")]
        [AttBindControl(eControlType.PROPERTY, "UserId")]        
        public int UserId
        {
            get { return m_userid; }
            set { m_userid = value; }
        }

        [AttField("UserName", eDBDataType.VARCHAR, 50)]
        [AttBindControl(eControlType.TEXTBOX, "txtUsername")]
        [AttSearchable]
        [AttKeyField]
        public string Username
        {
            get { return m_username; }
            set { m_username = value; }
        }

        [AttField("UserDesc", eDBDataType.VARCHAR, 250)]
        [AttBindControl(eControlType.TEXTBOX, "txtDescription")]
        [AttSearchable]
        public string UserDesc
        {
            set { m_userdesc = value; }
            get { return m_userdesc; }
        }

        [AttField("Password", eDBDataType.VARCHAR, 250)]        
        public string PasswordEncrypted
        {
            get { return m_password_enc; }
            set { m_password_enc = value; }
        }

        [AttBindControl(eControlType.TEXTBOX, "txtPassword")]
        public string Password
        {
            set { m_password_enc = TaugeEncryption.hrEncrypt(value, m_username); }
            get
            {
                return TaugeEncryption.hrDecrypt(m_password_enc, m_username);
            }
        }

        [AttField("UserType", eDBDataType.INT, 0)]
        [AttBindControl(eControlType.COMBOBOX, "cboUserType")]
        [AttSearchable]
        public eUserType UserType
        {
            get { return m_usertype; }
            set { m_usertype = value; }
        }


        [AttField("IsActive", eDBDataType.BIT, 0)]
        [AttBindControl(eControlType.CHECKBOX, "chkIsActive")]
        [AttSearchable]
        public Boolean IsActive
        {
            get { return m_isactive; }
            set { m_isactive = value; }
        }


        [AttField("EmailAddr", eDBDataType.VARCHAR, 250)]
        [AttBindControl(eControlType.TEXTBOX, "txtEmailAddress")]
        [AttSearchable]
        public string EmailAddress { get { return m_email_address; } set { m_email_address = value; } }

        
        
        [AttField("CekSum", eDBDataType.INT, 0)]
        public int CekSum { get { return getChecksum(); } set { m_ceksum = value; } }


        public Hashtable Accesses { set { m_accesses = value; } get { return m_accesses; } }
        public Hashtable Companies { set { m_companies = value; } get { return m_companies; } }
        public Hashtable Groups { set { m_groups = value; } get { return m_groups; } }
        public Hashtable CurrentAccesses { set { m_current_accesses = value; } get { return m_current_accesses; } }

        #endregion

        #region constructor
        public UserAccount(ITaugeFramework p_framework) : this(p_framework, "", "", "", "",eUserType.USER, true, false) { }
        public UserAccount(ITaugeFramework p_framework, string p_username, string p_userdesc, string p_password, string p_emailaddr, eUserType p_usertype, Boolean p_isactive, Boolean p_isencryptedpass):base(p_framework)
        {
            m_username = p_username;
            if (p_isencryptedpass)
                m_password_enc = p_password;
            else
                Password = p_password;
            m_usertype = p_usertype;
            m_isactive = p_isactive;
            m_userdesc = p_userdesc;
            m_email_address = p_emailaddr;
            
        }
        #endregion

        #region method
        private int getChecksum()
        {
            return TaugeEncryption.generateCheckSum(m_username, m_password_enc, Convert.ToInt32(m_usertype).ToString(), m_isactive.ToString());
        }
        public int getChecksum(string p_additional)
        {
            return TaugeEncryption.generateCheckSum(m_username, p_additional);
        }

        public void clearGroup()
        {
            m_groups.Clear();
        }
        public Boolean addGroup(string p_group_id)
        {
            //if (m_groups[p_group_id] == null)
            try
            {
                m_groups.Add(p_group_id, p_group_id);
                return true;
            }
            catch { return false; }
        }
        public int getChecksumGroup(string p_group_id)
        {
            return TaugeEncryption.generateCheckSum(m_username, p_group_id);
        }

        public void clearCompany()
        {
            m_companies.Clear();
        }
        public Boolean addCompany(string p_company_id)
        {
            try
            {
                m_companies.Add(p_company_id, p_company_id);
                return true;
            }
            catch { return false; }
        }
        public int getChecksumCompany(string p_comp_id)
        {
            return TaugeEncryption.generateCheckSum(m_username, p_comp_id);
        }

        public Boolean isAuthorizedCompany(string p_company_id)
        {
            if (m_companies[p_company_id] == null)
                return false;
            else
                return true;
        }

        public string getCSList()
        {
            Boolean bfirst = true;
            string result = "(";
            IDictionaryEnumerator en = this.Companies.GetEnumerator();
            while (en.MoveNext())
            {
                if (!bfirst)
                    result += ",";
                result += LibConstants.sqlStr(en.Value.ToString());
                bfirst = false;
            }
            result += ")";
            if (bfirst)
                return "('')";
            else
                return result;
        }



        public void clearAccess()
        {
            m_accesses.Clear();
        }
        public Boolean addAccess(string p_access_id)
        {
            try
            {
                m_accesses.Add(p_access_id, p_access_id);
                return true;
            }
            catch { return false; }
        }
        public int getChecksumAccess(string p_access_id)
        {
            return TaugeEncryption.generateCheckSum(m_username, p_access_id);
        }

        public Boolean isAuthorized(string p_access_id)
        {
            if (m_current_accesses[p_access_id] == null)
                return false;
            else
                return true;
        }

        public void LoadAccess(string p_company)
        {
            /*
            m_current_accesses.Clear();
            UserAccount tmp = new UserAccount();
            retreiveAccess(p_company, m_username, tmp, true);
            
            if(p_company!="")
                if (tmp.Companies[p_company] == null)
                    return;

            m_current_accesses = tmp.Accesses;
            m_companies = tmp.Companies;
            tmp.Accesses=null;
            tmp = null;
             **/

            try
            {
                string tmptbl = Program.dbsys.newTempTable();

                Program.dbsys.executeNonQuery("usp_useraccount_loadaccess " + LibConstants.sqlStr(m_username) + "," + LibConstants.sqlStr(tmptbl));

                UserAccount tmpusr = new UserAccount(m_framework);

                Hashtable htbl = new Hashtable();
                //group
                using (DataTable dt = Program.dbsys.executeDataTable("SELECT * FROM " + tmptbl + "U"))
                {
                    foreach (DataRow sdr in dt.Rows)
                    {
                        if (sdr["Username"].ToString() != "")
                        {
                            tmpusr.Username = sdr["Username"].ToString();
                            if (tmpusr.getChecksumGroup(sdr["UserGroupID"].ToString()) != LibConstants.toInt(sdr["CekSum"]))
                            {
                                htbl.Add(sdr["UserGroupID"].ToString().ToUpper(), sdr["UserGroupID"].ToString().ToUpper());
                            }
                        }
                    }
                    dt.Dispose();
                }

                using (DataTable dt = Program.dbsys.executeDataTable("SELECT * FROM " + tmptbl + "C"))
                {
                    foreach (DataRow sdr in dt.Rows)
                    {
                        if (!htbl.ContainsKey(sdr["UserID"].ToString().ToUpper()))
                        {
                            tmpusr.Username = sdr["UserID"].ToString();
                            if (tmpusr.getChecksumCompany(sdr["CsID"].ToString()) == LibConstants.toInt(sdr["CekSum"]))
                            {
                                tmpusr.addCompany(sdr["CsID"].ToString().ToUpper());
                            }
                        }
                    }
                    dt.Dispose();
                }

                using (DataTable dt = Program.dbsys.executeDataTable("SELECT * FROM " + tmptbl + "M"))
                {
                    foreach (DataRow sdr in dt.Rows)
                    {
                        if (!htbl.ContainsKey(sdr["UserID"].ToString().ToUpper()))
                        {
                            tmpusr.Username = sdr["UserID"].ToString();
                            if (tmpusr.getChecksumAccess(sdr["ModuleID"].ToString()) == LibConstants.toInt(sdr["CekSum"]))
                            {
                                tmpusr.addAccess(sdr["ModuleID"].ToString().ToUpper());
                            }
                        }
                    }
                    dt.Dispose();
                }


                Program.dbsys.executeNonQuery("DROP TABLE " + tmptbl + "U");
                Program.dbsys.executeNonQuery("DROP TABLE " + tmptbl + "M");
                Program.dbsys.executeNonQuery("DROP TABLE " + tmptbl + "C");

                if (p_company != "")
                    if (tmpusr.Companies[p_company] == null)
                        return;

                m_current_accesses = tmpusr.Accesses;
                m_companies = tmpusr.Companies;
                tmpusr.Accesses = null;
                tmpusr = null;
            }
            catch { }


        }

        public void retreiveAccess(string p_company, string p_target_username, UserAccount p_result, Boolean p_first)
        {
            if (!p_result.addGroup(p_target_username))
                return;

            UserAccount tmp = new UserAccount(m_framework);
            tmp.Username = p_target_username;
            if (!tmp.doRead())
                return;

            if (!tmp.IsActive)
                return;

            if (p_first == false && tmp.UserType != eUserType.GROUP)
                return;


            /*
            if (tmp.Companies[p_company] != null)
                p_result.addCompany(p_company);
             * */

            IDictionaryEnumerator en = tmp.Accesses.GetEnumerator();
            while (en.MoveNext())
            {
                p_result.addAccess(en.Value.ToString());
            }

            en = tmp.Companies.GetEnumerator();
            while (en.MoveNext())
            {
                p_result.addCompany(en.Value.ToString());
            }

            en = tmp.Groups.GetEnumerator();
            while (en.MoveNext())
            {
                retreiveAccess(p_company, en.Value.ToString(), p_result, false);
            }
        }

        public static UserAccount doLogin(string p_username, string p_password)
        {
            UserAccount tmp = new UserAccount(Program.Framework);
            tmp.Username = p_username;
            if (tmp.doRead())
            {
                if (tmp.Password == p_password && tmp.UserType == eUserType.USER && tmp.IsActive == true)
                {
                    return tmp;
                }
            }

            return null;


        }

        #endregion

        #region Abusinessunit member
        
        public override bool FillData(System.Data.DataRow p_sdr)
        {
            try
            {
                bool result = base.FillData(p_sdr);
                /*
                m_username = LibConstants.toStr(p_sdr["username"]);
                m_password_enc = p_sdr["pwd"].ToString();
                m_usertype = (eUserType)LibConstants.toInt(p_sdr["usertype"]);
                m_isactive = LibConstants.toBool(p_sdr["isactive"]);
                m_userdesc = p_sdr["userdesc"].ToString();
                if (getChecksum() != LibConstants.toInt(p_sdr["ceksum"]))
                    throw new Exception("Data Corrupted");
                */

                if (getChecksum() != m_ceksum)
                {
                    m_errormessage = "Data Corrupted";
                    return false;
                }
                return result;
                /*
                //read detail
                clearGroup();
                clearCompany();
                clearAccess();
                /*DataTable dt = m_db.executeDataTable("SELECT Username, UserGroupID AS Detail, CekSum, 'G' AS flag FROM UserGroup WHERE Username=" + Constants.sqlStr(m_username) +
                                                             " UNION ALL SELECT Username, UserModuleID AS Detail, CekSum, 'M' AS flag FROM UserModule WHERE Username=" + Constants.sqlStr(m_username) +
                                                             " UNION ALL SELECT Username, UserCompStruID AS Detail, CekSum, 'C' AS flag FROM UserCompStru WHERE Username=" + Constants.sqlStr(m_username)
                    );
                 */ /* */
                
                /*
                DataTable dt = new DataTable();
                foreach (DataRow sdr in dt.Rows)
                {
                    if (LibConstants.toInt(sdr["CekSum"]) == getChecksum(sdr["Detail"].ToString()))
                    {
                        if (sdr["flag"].ToString() == "G")
                            addGroup(sdr["Detail"].ToString());
                        else if (sdr["flag"].ToString() == "M")
                            addAccess(sdr["Detail"].ToString());
                        else if (sdr["flag"].ToString() == "C")
                            addCompany(sdr["Detail"].ToString());
                    }
                    else
                    {
                        string tblname = "";
                        string pkname = "";
                        string dtlname = "";

                        if (sdr["flag"].ToString() == "G")
                        {
                            tblname = "UserGroup";
                            pkname = "Username";
                            dtlname = "UserGroupID";
                        }
                        else if (sdr["flag"].ToString() == "M")
                        {
                            tblname = "UserModule";
                            pkname = "Username";
                            dtlname = "UserModuleID";
                        }
                        else if (sdr["flag"].ToString() == "C")
                        {
                            tblname = "UserCompStru";
                            pkname = "Username";
                            dtlname = "UserCompStruID";
                        }
                        // m_db.executeNonQuery("DELETE " + tblname + " WHERE " + pkname + "=" + Constants.sqlStr(m_username) + " AND " + dtlname + " = " + Constants.sqlStr(sdr["Detail"].ToString()));
                    }
                }
                dt.Dispose();


                return base.FillData(p_sdr);
                 * */
            }
            catch (Exception ex)
            {
                m_errormessage = ex.Message;
                return false;
            }
        }
/*
        public override System.Data.SqlClient.SqlCommand[] getActionCommand(string p_action)
        {
            //int i = 0;
            List<SqlCommand> atmp = new List<SqlCommand>();
            atmp.Add(new SqlCommand("DELETE UserGroup WHERE Username=" + LibConstants.sqlStr(m_username)));
            atmp.Add(new SqlCommand("DELETE UserModule WHERE Username=" + LibConstants.sqlStr(m_username)));
            atmp.Add(new SqlCommand("DELETE UserCompStru WHERE Username=" + LibConstants.sqlStr(m_username)));
            atmp.Add(new SqlCommand("usp_UserAccount_action " + LibConstants.sqlStr(p_action) + "," +
                               LibConstants.sqlStr(m_username) + "," +
                               LibConstants.sqlStr(m_userdesc) + "," +
                               LibConstants.sqlStr(m_password_enc) + "," +
                               LibConstants.sqlNum(Convert.ToInt32(m_usertype)) + "," +
                               LibConstants.sqlBool(m_isactive) + "," +
                               getChecksum() + "," +
                               LibConstants.sqlStr("")));//Program.ActiveUser.Username)));

            if (p_action != LibConstants.eDELETE)
            {
                IDictionaryEnumerator en = m_groups.GetEnumerator();
                while (en.MoveNext())
                {
                    string s = en.Value.ToString();
                    atmp.Add(new SqlCommand("INSERT INTO UserGroup(Username, UserGroupID, CekSum) VALUES (" +
                                                            LibConstants.sqlStr(m_username) + "," +
                                                            LibConstants.sqlStr(s) + "," +
                                                            getChecksum(s) + ")"));
                }

                en = m_companies.GetEnumerator();
                while (en.MoveNext())
                {
                    string s = en.Value.ToString();
                    atmp.Add(new SqlCommand("INSERT INTO UserCompStru(Username, UserCompStruID, CekSum) VALUES (" +
                                                            LibConstants.sqlStr(m_username) + "," +
                                                            LibConstants.sqlStr(s) + "," +
                                                            getChecksum(s) + ")"));
                }

                en = m_accesses.GetEnumerator();
                while (en.MoveNext())
                {
                    string s = en.Value.ToString();
                    atmp.Add(new SqlCommand("INSERT INTO UserModule(Username, UserModuleID, UserCompStruID, CekSum) VALUES (" +
                                                            LibConstants.sqlStr(m_username) + "," +
                                                            LibConstants.sqlStr(s) + "," +
                                                            LibConstants.sqlStr("< All >") + "," +
                                                            getChecksum(s) + ")"));
                }
            }
            return atmp.ToArray();

        }
*/


        /*
        public override string getQuerySql(){ return "SElECT TOP 1 * FROM UserAccount";}

        public override string  getCondition(System.Data.DataRow p_dr, string p_name)
        {
            return "Username = " + Constants.sqlStr(p_dr["Username"].ToString());
        }
    
        public override string getCondition(string p_name)
        {
            return "Username = " + Constants.sqlStr(this.m_username);
        }
    */
        #endregion


    }



    [AttBuMgr(
            UnitName = "User",
        //ListSql = "SELECT UserId, Username, UserDesc AS Keterangan, EmailAddr AS Email, CASE WHEN UserType=1 THEN 'GROUP' ELSE 'USER' END AS Tipe, IsActive AS Aktif FROM UserAccount WHERE 1<>2 ",
            Unit = "TaugeFramework.BusinessUnit.User.UserAccount",
            UnitUI = "TaugeFramework.BusinessUnit.User.UserUI",
            ImageRes = "User",
            DllFile = "TaugeFramework.exe",
            ListIsDistinct = false,
            ListColumns = new string[] { "UA.UserId AS Id", "UA.Username", "UA.UserDesc AS Keterangan", "UA.EmailAddr AS Email", "CASE WHEN UA.UserType = 1 THEN 'GROUP' ELSE 'USER' END AS Tipe", "UA.IsActive AS Aktif" },
            ListTables = new string[] { "UserAccount UA " },
            ListKeys = new string[] { "Id" },
            ListOrders = new string[] { "UA.UserId" }            
       )
   ]
    public class UserAccountManager : ABusinessUnitManager
    {
        public UserAccountManager() : base(Program.Framework) { }
    }


}
